package com.atguigu.gulimall.authserver.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.common.vo.MemberRespVo;
import com.atguigu.gulimall.authserver.feign.MemberFeignService;
import com.atguigu.gulimall.authserver.utils.HttpUtils;
import com.atguigu.gulimall.authserver.vo.SocialUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * 专门处理社交登陆请求
 */
@Controller
@Slf4j
public class OAuthController {

    @Resource
    private MemberFeignService memberFeignService;

    /**
     * 社交登陆功能：请求微博的登录页面 --> 用户进行认证  -->  微博返回谷粒商城下的/oauth2.0/weibo/success路径一个code
     *             --> 由于code和client_secret都不能在网站url中暴露，因此要在后端进行处理，于是有了下面的映射，我们的任务是
     *             拿到code和client_secret再发送到微博去获取到一个access_token，有了它我们就可以为所欲为了
     *             --> 总之赶紧从微博拿到我们谷粒商城觉得有用的信息作为验证信息，登陆成功后返回首页
     * 注意：code是用户每登陆一次返回的code当次有效，如果重新登陆的话，原先的code失效
     *      但是根据code获得的access_token在一定时间范围内都是有效的，即在一定时间内，你即使更换了code，获取到的access_token
     *      也是一样的。
     * @param code
     * @return
     */
    @RequestMapping("/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code")String code, HttpSession session) throws Exception{
        //1.根据code换取access-token
        Map<String,String> query = new HashMap<>();
        query.put("client_id","YOUR_CLIENT_ID");
        query.put("client_secret","YOUR_CLIENT_SECRET");
        query.put("grant_type","authorization_code");
        query.put("redirect_uri","http://gulimall.com/oauth2.0/weibo/success");
        query.put("code","CODE");
        HttpResponse response = HttpUtils.doPost("api.weibo.com", "/oauth2/access_token","post",null,null,query );
        //2.登陆成功就跳回首页

        if(response.getStatusLine().getStatusCode() == 200){
            //获取到了access_token
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, new TypeReference<SocialUser>() {
            });

            //谷粒商城登陆还需要分情况
            //1.当前用户如果是通过社交登录第一次进网站，需要为该用户自动注册(为当前用户生成一个会员信息账号
            // ,以后这个社交账号(即微博的登录信息)就对应指定的会员)
            //如何将用户的微博信息与谷粒商城系统进行关联？即怎么为用户自动注册。既然我们谷粒商城拿不到用户在
            //微博上的唯一标识(用户名和密码),那就看微博能给我们什么作为唯一标识(我好卑微啊，既要等着用户授权自己
            // 可以获取用户自己的信息还只能拿到微博愿意给我的信息，为了吸引流量也是选择放下了身段啊)
            //那么微博愿意给我们什么信息作为用户的注册信息呢？他一定得是唯一的，即一个微博用户对应一个信息，这样
            //在谷粒商城系统里就对应一个用户id，存在ums_member这张表里。这个唯一的信息就是在拿到access_token
            //同时获取到的uid，我们刚刚把返回值封装在了SocialUser这个Vo对象里面。这个uid是永恒的，即使access_token
            //失效了也会以至于该用户绑定，就像用户的微博名和密码一样
            R oauthlogin = memberFeignService.oauthlogin(socialUser);
            if(oauthlogin.getCode() == 0){      //自动注册并登陆成功
                MemberRespVo data = oauthlogin.getData("data", new TypeReference<MemberRespVo>() {
                });
                System.out.println("用户信息："+data);
                log.info("登陆成功，用户信息：{}",data);
//                session.setAttribute("loginUser",data);  既然是session，那我们在任何一个位置做都是可以的，我选择在LoginController的login方法中进行分布式session的解决
                return "redirect:http://gulimall.com";
            }else {
                return "redirect:http://auth.gulimall.com/login.html";
            }

        }else {
            return "redirect:http://auth.gulimall.com/login.html";
        }

    }
}
